package com.yexiao.cofe.business.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.yexiao.cofe.common.entity.SmsNode;
import com.yexiao.cofe.business.service.SmsService;
import com.yexiao.core.util.IDateUtil;
import com.yexiao.core.util.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

    private final Random random = new Random();
    private final int maxCodeSize = 8;
    private final int minCodeSize = 4;
    private int sms_size = 4;

    // 默认短信缓存时间  5分钟
    private final long DEFAULT_EXPIRE_TIME = 1000 * 60 * 3L;

    /**
     * 短信本地缓存
     */
    Map<String, SmsNode> smsCodeMap = new ConcurrentHashMap<>();

    /*
     * 定时器，定期删除本地缓存中过期的短信
     * 每3分钟执行一次
     */
    {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                long nowTime = IDateUtil.nowSecond();
                smsCodeMap.forEach((k, v) -> {
                    if(nowTime > v.getExpireTime()) {
                        smsCodeMap.remove(k);
                    }
                });
            }

        }, DEFAULT_EXPIRE_TIME, DEFAULT_EXPIRE_TIME);
    }

    private int generateCode(int size) {
        // 控制验证码长度
        if(size > maxCodeSize) {
            size = maxCodeSize;
        } else if(size < minCodeSize) {
            size = minCodeSize;
        }

        int code = 0;
        for (int i = 0; i < size; i++) {
            int temp = random.nextInt(10);
            code = code * 10 + temp;
        }

        return code;
    }

    /**
     * 设置验证码缓存
     * 默认缓存时间：3分钟
     * 相同key会进行覆盖
     */
    private void setCache(String key, int code) {
        long nowSecond = IDateUtil.nowSecond();
        smsCodeMap.put(key, new SmsNode(code, nowSecond + DEFAULT_EXPIRE_TIME));
    }

    @Override
    public void changeSmsSize(int size) {
        this.sms_size = size;
    }

    @Override
    public boolean verityCode(String phone, int code) {
        SmsNode smsNode = smsCodeMap.get(phone);

        // 验证码不存在
        if(smsNode == null) {
            log.error("smsNode is null");
            return false;
        }

        // 验证成功，删除验证码缓存
        if(code == smsNode.getCode()) {
            removeCodeCache(phone);
            return true;
        }

        return false;
    }

    @Override
    public JSONObject getCode(String phone) {
        int code = generateCode(sms_size);
        setCache(phone, code);

        return JSONUtil.of("code", code);
    }

    private void removeCodeCache(String phone) {
        smsCodeMap.remove(phone);
    }
}
